
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
let uid = 0

function MyPromise(executor){
  this.uid = uid++
  this.status = PENDING
  this.fulfilledCallbackList = []
  this.rejectedCallbackList = []
  this.value = null
  this.error = null 

  const resolve = (value)=>{
    setTimeout(() => {
      if(this.status === PENDING){
        this.value = value
        this.fulfilledCallbackList.forEach(fn=>{
          fn(this.value)
        })
      }
    });
  }

  const reject = (error)=>{
    setTimeout(() => {
      if (this.status === PENDING) {
        this.error = error
        this.rejectedCallbackList.forEach(fn => {
          fn(this.error)
        })
      }
    });
  }


  try {
    executor(resolve,reject)
  } catch (error) {
    throw error
  }
}
MyPromise.prototype.then = function(onFulfilled,onRejected){
  onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : (value)=>value
  onRejected = typeof onRejected === 'function' ? onRejected : (error)=> { throw error }
  let self = this
  let newPromise
  if(this.status === PENDING){
    newPromise = new MyPromise((resolve, reject) => {
        this.fulfilledCallbackList.push((value) => {
            try {
              let x = onFulfilled(value)
              resolvePromise(newPromise, x, resolve, reject)
            } catch (error) {
              reject(error)
            }
        })
        this.rejectedCallbackList.push((e) => {
            try {
              let x = onRejected(e)
              resolvePromise(newPromise, x, resolve, reject)
            } catch (error) {
              reject(error)
            }
        })
    })
    
  }else if(this.status === FULFILLED){
    newPromise = new MyPromise((resolve,reject)=>{
      setTimeout(() => {
        try {
          let x = onFulfilled(self.value)
          resolvePromise(newPromise, x, resolve, reject)
        } catch (error) {
          reject(error)
        }
        
      });
    })
    
  }else{
    newPromise = new MyPromise((resolve, reject) => {
      setTimeout(() => {
        try {
          let x = onRejected(self.error)
          resolvePromise(newPromise, x, resolve, reject)
        } catch (error) {
          reject(error)
        }

      });
    })
  }
  return newPromise
}
MyPromise.prototype.catch = function (onRejected){
  this.then(null,onRejected)
}

Promise.prototype.finally = function(callback){
  this.then(value=>{
    return MyPromise.resolve(callback()).then(()=>{
      resolve(value)
    })
  },error=>{
    return Promise.reject(callback()).then(()=>{
      reject(error)
    })
  })
}

MyPromise.all = function(promises){
  let n = promises.length
  let ret = new Array(n)
  let count = 0
  return new MyPromise((resolve,reject)=>{
    for (let i = 0; i < n; i++) {
      MyPromise.resolve(promises[i]).then(data=>{
        ret[i] = data
        count++
        if (count === n){
          resolve(ret)
        }
      }).catch(err => {
        reject(err);
      })
      
    }
  })
 
 
}

MyPromise.race = function(array){
  let n = array.length
  return new MyPromise((resolve, reject) => {
    for (let i = 0; i < n; i++) {
      MyPromise.resolve(array[i]).then(data=>{
        resolve(data)
        return 
      }).catch(err => {
        reject(err);
      })
    }
  })
}


MyPromise.resolve = function (param){
  if (param instanceof MyPromise) return param;
  return new MyPromise((resolve, reject) => {
    if (param && param.then && typeof param.then === 'function') {
      // param 状态变为成功会调用resolve，将新 Promise 的状态变为成功，反之亦然
      param.then(resolve, reject);
    } else {
      resolve(param);
    }
  })
}
MyPromise.reject = function(reason){
  return new MyPromise((resolve,reject)=>{
    reject(reason)
  })
}
// 处理x的值 将x充promise解封为原始值
function resolvePromise(newPromise,x,resolve,reject){
  if(x instanceof MyPromise){
    if(x.status === PENDING){
      x.then(y=>{
        resolvePromise(newPromise,y,resolve,reject)
      },error=>{
        rejext(error)
      })
    }else{
      x.then(resolve,reject)
    }
  }else{
    resolve(x)
  }
}
// let promise1 = new MyPromise((resolve, reject) => {
//   setTimeout(() => {
//     resolve(123)
//   }, 1000);
// });
// let x1 = promise1.then(data => {
//   console.log("第一次展示", data.toString());
// });

// let x2 = promise1.then(data => {
//   console.log("第二次展示", data.toString());
// });

// let x3 = promise1.then(data => {
//   console.log("第三次展示", data.toString());
// });

 let p = new MyPromise((resolve, reject) => {
   setTimeout(() => {
     resolve(1);

   }, 1000);
}).then((data)=>{
  console.log('1',data)
  return new MyPromise((resolve,reject)=>{
    resolve(2)
  })
}).then((data)=>{
  console.log(data.toString());
})
// console.log('p', p)
